# formfactor.py
#
# Classes to deal with different form factors computations

import hemicube

class FormFactorEngine():
    def computeFormFactorsForPatch(self, patch):
        pass

    def computeFormFactorForPatchiToPatchj(self, patch_i, patch_j):
        pass

    def defaultFormFactor(self):
        pass

    def memoizeFormFactors(self, max_patches_to_memoize):
        pass

    def memoizedFormFactors(self):
        pass

    def toString(self):
        return "FormFactorEngine"

class HemicubeFormFactorEngine(FormFactorEngine):
    def __init__(self, patches, delta_formfactors=None, resolution=256, display_list=None, arrays=None, createGLUTRenderingContext=True, memoize=False, max_patches_to_memoize=0):
        self.patches = patches
        self.delta_formfactors = delta_formfactors
        self.resolution = resolution
        self.display_list = display_list
        self.arrays = arrays
        self.memoize = memoize
        self.max_patches_to_memoize = max_patches_to_memoize
        self.memoized_patches = {}
        self.num_patches_memoized = 0

        if self.delta_formfactors is None:
            self.delta_formfactors = hemicube.createHemicubeDeltaFormFactors(self.resolution)

        if createGLUTRenderingContext is True:
            hemicube.createHemicubeGLUTRenderingContext(self.resolution)

    def computeFormFactorsForPatch(self, patch):
        formfactors = None
        if self.memoize is True:
            try:
                formfactors = self.memoized_patches[patch]
            except KeyError:
                if self.num_patches_memoized < self.max_patches_to_memoize:
                    self.memoized_patches[patch] = hemicube.computeHemicubeGLFormFactorsForPatch(patch, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
                    formfactors = self.memoized_patches[patch]
                    self.num_patches_memoized += 1
                else:
                    formfactors = hemicube.computeHemicubeGLFormFactorsForPatch(patch, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
        else:
            formfactors = hemicube.computeHemicubeGLFormFactorsForPatch(patch, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
        return formfactors

    def computeFormFactorForPatchiToPatchj(self, patch_i, patch_j):
        formfactor = self.defaultFormFactor()
        if self.memoize is True:
            try:
                formfactors_i = self.memoized_patches[patch]
                try:
                    formfactor = self.memoized_patches[patch_i][patch_j]
                except KeyError:
                    self.memoized_patches[patch_i][patch_j] = hemicube.computeHemicubeGLFormFactorForPatchiToPatchj(patch_i, patch_j, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
                    formfactor = self.memoized_patches[patch_i][patch_j]
            except KeyError:
                if self.num_patches_memoized < self.max_patches_to_memoize:
                    self.memoized_patches[patch_i] = {}
                    self.memoized_patches[patch_i][patch_j] = hemicube.computeHemicubeGLFormFactorForPatchiToPatchj(patch_i, patch_j, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
                    formfactor = self.memoized_patches[patch_i][patch_j]
                    self.num_patches_memoized += 1
                else:
                    formfactor = hemicube.computeHemicubeGLFormFactorForPatchiToPatchj(patch_i, patch_j, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
        else:
            formfactor = hemicube.computeHemicubeGLFormFactorForPatchiToPatchj(patch_i, patch_j, self.patches, self.delta_formfactors, self.resolution, self.display_list, self.arrays)
        return formfactor

    def defaultFormFactor(self):
        return 0.0

    def memoizeFormFactors(self, max_patches_to_memoize):
        self.memoize = True
        self.memoized_patches = {}
        self.max_patches_to_memoize = max_patches_to_memoize
        self.num_patches_memoized = 0

    def memoizedFormFactors(self):
        return self.memoized_patches

    def toString(self):
        return "HemicubeFormFactorEngine"

    def createHemicubeGLUTRenderingContext(self):
        hemicube.createHemicubeGLUTRenderingContext(self.resolution)
